<template>
  <div class="edit_container">
    <div class="edit_content" :style="`transform: scale(${scale},${scale})`">
      <NodeEdit :data="getPlusData" :editType="editType" />
    </div>
    <a-drawer
      :title="drawerTitle"
      :destroyOnClose="true"
      :maskClosable="false"
      placement="right"
      width="550"
      closable
      :visible="visible"
      :after-visible-change="afterVisibleChange"
      @close="onClose"
      :bodyStyle="{ padding: 0 }"
    >
      <T_examineAndApprove
        :requestConfig="requestConfig"
        :nodeData="editNodeObj"
        :customFields="customFields"
        :approvalNodes="getApprovalNodes"
        v-if="editNodeType === 'E'"
        @close="onClose"
      />
      <T_originator
        :requestConfig="requestConfig"
        :nodeData="editNodeObj"
        v-if="editNodeType === 'O'"
        @close="onClose"
      />
      <T_subProcess
        :requestConfig="requestConfig"
        :nodeData="editNodeObj"
        :customFields="customFields"
        v-if="editNodeType === 'S'"
        @close="onClose"
      />
      <T_timer
        :nodeData="editNodeObj"
        v-if="editNodeType === 'T'"
        @close="onClose"
      />
      <T_condition
        :nodeData="editNodeObj"
        :customFields="customFields"
        v-if="editNodeType === 'C'"
        @close="onClose"
      />
    </a-drawer>
    <ButtonGroup class="edit_actions">
      <Button @click="logData"> 打印日志 </Button>
      <!-- <Button @click="scaleEditor(-0.25)"> - </Button>
      <Button @click="scaleEditor(0.25)"> + </Button> -->
    </ButtonGroup>
  </div>
</template>

<script>
import Vue from "vue";
import EventBus from "./components/eventBus";
import NodeEdit from "./nodeEdit.vue";
import T_examineAndApprove from "./components/nodeEditTemplate/T_examineAndApprove.vue";
import T_originator from "./components/nodeEditTemplate/T_originator.vue";
import T_subProcess from "./components/nodeEditTemplate/T_subProcess.vue";
import T_timer from "./components/nodeEditTemplate/T_timer.vue";
import T_condition from "./components/nodeEditTemplate/T_condition.vue";

import initNodeData from "./initNodeData";
// antd组件引用
import Drawer from "ant-design-vue/lib/drawer";
import Button from "ant-design-vue/lib/button";
import Modal from "ant-design-vue/lib/modal";

// antd组件样式
import "ant-design-vue/lib/icon/style/css";
import "ant-design-vue/lib/drawer/style/css";
import "ant-design-vue/lib/button/style/css";
import "ant-design-vue/lib/modal/style/css";
import "ant-design-vue/lib/tree/style/css";
import "ant-design-vue/lib/input/style/css";
import "ant-design-vue/lib/select/style/css";
import "ant-design-vue/lib/table/style/css";
import "ant-design-vue/lib/tabs/style/css";
import "ant-design-vue/lib/row/style/css";
import "ant-design-vue/lib/col/style/css";
import "ant-design-vue/lib/radio/style/css";
import "ant-design-vue/lib/progress/style/css";
import "ant-design-vue/lib/checkbox/style/css";
import "ant-design-vue/lib/switch/style/css";
import "ant-design-vue/lib/input-number/style/css";
import "ant-design-vue/lib/message/style/css";

Vue.use(Drawer);
Vue.use(Modal);

const { Group } = Button;
const ButtonGroup = Group;
export default {
  name: "App",
  props: {
    fields: {
      type: Array,
      default: () => {
        return [];
      },
    },
    requestConfig: {
      type: Object,
      require: true,
    },
    editType: { default: 1, type: Number },
    data: Object,
  },
  components: {
    NodeEdit,
    T_examineAndApprove,
    T_originator,
    T_subProcess,
    T_timer,
    T_condition,

    ButtonGroup,
    Button,
  },
  data() {
    return {
      customFields: JSON.parse(JSON.stringify(this.fields)),
      scale: 1,
      visible: false,
      editNodeObj: null,
      editorData:
        this.editType === 1
          ? initNodeData("O")
          : this.formattingPropsData(this.data),
    };
  },

  watch: {
    editNodeObj(val) {
      this.visible = !!val;
    },
    fields(val) {
      this.customFields = val;
    },
  },

  computed: {
    drawerTitle() {
      if (!this.editNodeObj) return "";
      let type = this.editNodeObj.type;
      switch (type) {
        case "O":
          return "发起人节点设置";
        case "E":
          return "审批节点设置";
        case "S":
          return "子程序节点设置";
        case "T":
          return "计时节点设置";
        case "C":
          return "条件节点设置";
        default:
          return "";
      }
    },
    editNodeType() {
      return this.editNodeObj ? this.editNodeObj.type : null;
    },
    hasConditionNode() {
      return (
        this.editorData.conditionNode &&
        this.editorData.conditionNode.length > 0
      );
    },
    hasShuntNode() {
      return this.editorData.shuntNode && this.editorData.shuntNode.length > 0;
    },
    hasChildNode() {
      return !!this.editorData.childNode;
    },
    getPlusData() {
      let copyData = JSON.parse(JSON.stringify(this.editorData));
      // 添加一些其他的属性(
      // 1.当前节点父节点id,
      // 2.当前节点路径,
      // 3.当前条件节点的权重，
      // 4.当前条件节点是不是默认的执行分支，
      // 5.当前审批节点是否是分支节点下的审批节点，)
      // 到当前节点上
      function appendOtherDataForItem(obj, { path, prevId, c_default_branch }) {
        let nodeId = obj.nodeId;
        obj.path = path;
        if (prevId) {
          obj.prevId = prevId;
        }
        if (obj.type === "C") {
          // 如果是条件，
          // 设置优先级(按在数组中的排序设置)
          let priority = path.slice(-1)[0];
          obj.props.priority = priority;
          // 设置是否是默认的分支
          obj.props.isDefault = c_default_branch;
        }

        function set_c_content() {
          let content = "",
            conditions = obj.props.conditions;
          content = conditions
            .map(
              (e, i) =>
                `${e.fieldName} ${e.symbolName} ${e.filedValue}${
                  i === conditions.length - 1 ? "" : " " + e.logicName + " "
                }`
            )
            .join("");
          obj.content = content;
        }

        function set_t_content() {
          let content = "";
          if (
            obj.props.day ||
            obj.props.hour ||
            obj.props.minute ||
            obj.props.second
          ) {
            content = `将于${obj.props.day ? obj.props.day + "天" : ""}${
              obj.props.hour ? obj.props.hour + "小时" : ""
            }${obj.props.minute ? obj.props.minute + "分钟" : ""}${
              obj.props.second ? obj.props.second + "秒" : ""
            } 后流转`;
          } else {
            content = "";
          }

          obj.content = content;
        }

        function set_e_content() {
          let content = "";
          switch (obj.props.assigneeType) {
            case 1:
              content = [...obj.props.approverRole, ...obj.props.approvers]
                .map((e) => e.name)
                .join(",");
              break;
            case 2:
              content = "发起者主管";
              break;
            case 3:
              content = "发起者本人";
              break;
            case 4:
              content = "部门主管";
              break;

            case 5:
              content = "变量";
              break;
            case 6:
              content = "环节";
              break;
            case 7:
              content = "服务";
              break;
          }
          obj.content = content;
        }

        function set_s_content() {
          let content = "";
          switch (obj.props.initiateType) {
            case 1:
              content = [...obj.props.initiateRole, ...obj.props.initiator]
                .map((e) => e.name)
                .join(",");
              break;
            case 2:
              content = "部门主管";
              break;
            case 3:
              content = "发起者主管";
              break;
            case 4:
              content = "发起者本人";
              break;
          }
          obj.content = content;
        }

        function set_o_content() {
          let content = "";
          content = [...obj.props.initiateRole, ...obj.props.initiator]
            .map((e) => e.name)
            .join(",");
          obj.content = content;
        }

        switch (obj.type) {
          case "C":
            set_c_content();
            break;
          case "T":
            set_t_content();
            break;
          case "E":
            set_e_content();
            break;
          case "S":
            set_s_content();
            break;
          case "O":
            set_o_content();
            break;
        }

        for (let key in obj) {
          switch (key) {
            case "childNode":
              if (!!obj.childNode) {
                appendOtherDataForItem(obj.childNode, {
                  path: [...path, "childNode"],
                  prevId: nodeId,
                });
              }
              break;
            case "shuntNode":
              for (let i = 0, len = obj.shuntNode.length; i < len; i++) {
                appendOtherDataForItem(obj.shuntNode[i], {
                  path: [...path, "shuntNode", i],
                  prevId: nodeId,
                });
              }
              break;
            case "conditionNode":
              for (let i = 0, len = obj.conditionNode.length; i < len; i++) {
                // 是不是最后一个
                let isLast = i === len - 1;
                // 有没有条件设置
                let isEmptyBranch =
                  obj.conditionNode[i].props.conditions.length === 0;
                appendOtherDataForItem(obj.conditionNode[i], {
                  path: [...path, "conditionNode", i],
                  prevId: nodeId,
                  c_default_branch: isLast && isEmptyBranch,
                });
              }
              break;
          }
        }
      }

      appendOtherDataForItem(copyData, { path: [], prevId: "" });
      return copyData;
    },

    getApprovalNodes() {
      let currentId = this.editNodeObj.nodeId;
      let copyData = JSON.parse(JSON.stringify(this.editorData));
      let approvalNodes = [];
      function findApprovalNode(obj) {
        if (obj.type === "E" && currentId !== obj.nodeId) {
          // 是审批节点
          approvalNodes.push({
            name: obj.props.title,
            value: obj.nodeId,
          });
        }

        if (obj.conditionNode && obj.conditionNode.length > 0) {
          for (let v of obj.conditionNode) {
            findApprovalNode(v);
          }
        }

        if (obj.shuntNode && obj.shuntNode.length > 0) {
          for (let v of obj.conditionNode) {
            findApprovalNode(v);
          }
        }

        if (obj.childNode) {
          findApprovalNode(obj.childNode);
        }
      }
      findApprovalNode(copyData);
      return approvalNodes;
    },
  },
  mounted() {
    EventBus.$on("ADD_CHILD", this.addChild);
    EventBus.$on("ADD_C_BRANCH", (path) => this.addBranch(path, "C"));
    EventBus.$on("ADD_E_BRANCH", (path) => this.addBranch(path, "E"));
    EventBus.$on("ADD_BRANCH_ITEM", (path, type) =>
      this.addBranchItem(path, type)
    );
    // EventBus.$on("ADD_E_BRANCH_ITEM", (path) => this.addBranchItem(path, "E"));
    EventBus.$on("REMOVE_NODE", this.removeNode);
    EventBus.$on("EDIT_NODE", this.editNode);
    EventBus.$on("UPDATE_NODE", this.updateNode);
  },

  beforeDestroy() {
    EventBus.$off("ADD_CHILD");
    EventBus.$off("ADD_C_BRANCH");
    EventBus.$off("ADD_E_BRANCH");
    EventBus.$off("ADD_C_BRANCH_ITEM");
    EventBus.$off("ADD_E_BRANCH_ITEM");
    EventBus.$off("REMOVE_NODE");
    EventBus.$off("EDIT_NODE");
    EventBus.$off("UPDATE_NODE");
  },

  methods: {
    formattingPropsData(data) {
      data = JSON.parse(JSON.stringify(data));
      let reverseTypeMap = {
        start: "O",
        approver: "E",
        timer: "T",
        condition: "C",
        subFlow: "S",
      };

      function handleNodeObj(obj) {
        for (let key in obj) {
          if (key === "type") {
            obj.type = reverseTypeMap[obj.type];
          }

          if (key === "properties") {
            obj.props = obj.properties;
            delete obj.properties;
          }

          if (key === "conditionNodes" && obj.conditionNodes.length > 0) {
            if (obj.conditionType === "interflow") {
              obj.conditionNode = obj.conditionNodes;
            }
            if (obj.conditionType === "condition") {
              obj.shuntNode = obj.conditionNodes;
            }
            delete obj.conditionNodes;
            delete obj.conditionType;
          }

          if (key === "childNode") {
            handleNodeObj(obj.childNode);
          }
        }
      }

      handleNodeObj(data);
      return data;
    },
    getData() {
      let data = JSON.parse(JSON.stringify(this.getPlusData));
      let typeMap = {
        O: "start",
        E: "approver",
        T: "timer",
        C: "condition",
        S: "subFlow",
      };
      function handleNodeObj(obj) {
        for (let key in obj) {
          if (key === "type") {
            obj.type = typeMap[obj.type];
          }

          if (key === "props") {
            obj.properties = obj.props;
            delete obj.props;
          }
          if (key === "conditionNode") {
            if (obj.conditionNode.length > 0) {
              obj.conditionNodes = obj.conditionNode;
              obj.conditionType = "interflow";
            }
            delete obj.conditionNode;
          }
          if (key === "shuntNode" && obj.shuntNode.length > 0) {
            if (obj.shuntNode.length > 0) {
              obj.conditionNodes = obj.shuntNode;
              obj.conditionType = "condition";
            }
            delete obj.shuntNode;
          }

          if (key === "childNode") {
            handleNodeObj(obj.childNode);
          }
        }
      }

      handleNodeObj(data);
      return data;
    },
    getNodeTitle(type) {
      switch (type) {
        case "O":
          return "发起人节点标题";
        case "E":
          return "审批节点标题";
        case "S":
          return "子程序节点标题";
        case "T":
          return "计时节点标题";
        case "C":
          return "条件节点标题";
        default:
          return "";
      }
    },
    // editorSetting() {
    //   this.$refs.editorSettingModal &&
    //     this.$refs.editorSettingModal.showModal();
    //   // this.editorSettingModal = true;
    // },
    closeForEditorSettingModal() {
      // this.editorSettingModal = false;
    },
    scaleEditor(range) {
      this.scale += range;
    },
    afterVisibleChange(val) {},
    showDrawer() {
      this.visible = true;
    },
    onClose() {
      // this.visible = false;
      this.editNodeObj = null;
    },

    getDataForPath(path) {
      let find = this.editorData;
      for (let v of path) {
        find = find[v];
      }
      return find;
    },
    addChild(path, type, isBranchEndAdd) {
      let find = this.getDataForPath(path);
      // let obj = {
      //   type,
      //   props: {
      //     title: this.getNodeTitle(type),
      //   },
      // };
      let obj = initNodeData(type);
      if (
        find.conditionNode &&
        find.conditionNode.length > 0 &&
        !isBranchEndAdd
      ) {
        obj.conditionNode = JSON.parse(JSON.stringify(find.conditionNode));
        delete find.conditionNode;
      }
      if (find.shuntNode && find.shuntNode.length > 0 && !isBranchEndAdd) {
        obj.shuntNode = JSON.parse(JSON.stringify(find.shuntNode));
        delete find.shuntNode;
      }
      if (!!find.childNode) {
        obj.childNode = JSON.parse(JSON.stringify(find.childNode));
      }
      this.$set(find, "childNode", obj);
    },
    addBranch(path, type) {
      let find = this.getDataForPath(path);
      let obj = {
        type,
        props: {
          title: this.getNodeTitle(type),
        },
      };
      let branchDataArr = [0, 1].map((e) => initNodeData(type, true));
      this.$set(
        find,
        type === "C" ? "conditionNode" : "shuntNode",
        branchDataArr
      );
      // this.$set(find, type === "C" ? "conditionNode" : "shuntNode", [
      //   obj,
      //   { ...obj },
      // ]);
    },
    addBranchItem(path, type) {
      let find = this.getDataForPath(path);
      // let obj = {
      //   type,
      //   props: {
      //     title: this.getNodeTitle(type),
      //   },
      // };
      let obj = initNodeData(type, true);
      find.push(obj);
    },
    removeNode(path) {
      let lastPathKey = path[path.length - 1];
      let isBranchNode = typeof lastPathKey === "number";
      let branchData = [];
      if (isBranchNode) {
        branchData = this.getDataForPath(path.slice(0, -1));
        if (branchData.length > 2) {
          // 可以删掉分支项
          branchData.splice(lastPathKey, 1);
          return;
        } else {
          // 直接删掉分支
          let branchParent = this.getDataForPath(path.slice(0, -2));
          this.$set(branchParent, path[path.length - 2], []);
          return;
        }
      }
      let parent = this.getDataForPath(path.slice(0, -1));
      let find = this.getDataForPath(path);
      if (
        (!parent.conditionNode || parent.conditionNode.length === 0) &&
        (!parent.shuntNode || parent.shuntNode.length === 0)
      ) {
        this.$set(parent, "conditionNode", find.conditionNode);
        this.$set(parent, "shuntNode", find.shuntNode);
      }
      this.$set(parent, "childNode", find.childNode);
    },
    // 激活编辑节点
    editNode(nodeInfo) {
      this.editNodeObj = nodeInfo;
    },
    // 根据节点传回的数据更新流程引擎的数据
    updateNode({ path, dataProps, nodeId }) {
      let current = this.getDataForPath(path);
      this.$set(current, "props", dataProps);
      this.$nextTick(() => {
        // 更新节点校验状态
        const UPDATE_NODE_VERIFYINFO = "UPDATE_NODE_VERIFYINFO_" + nodeId;
        EventBus.$emit(UPDATE_NODE_VERIFYINFO);
      });
    },

    logData() {
      console.log(this.editorData);
      console.log("==>,", this.getPlusData);
    },
  },
};
</script>

<style>
.flow_editor {
  position: relative;
  text-align: left;
  min-width: 50%;
  min-height: 100%;
  background: #ebeef5;
}
.edit_container {
  text-align: center;
  position: relative;
  background: #ebeef5;
  overflow-x: auto;
  height: 100%;
}

.edit_container::-webkit-scrollbar {
  width: 5px;
}
.edit_container::-webkit-scrollbar-thumb {
  border-radius: 10px;
  -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.1);
  background: #ddd;
}

.edit_actions {
  position: absolute !important;
  top: 50px;
  left: 150px;
}

.edit_content {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  z-index: 0;
}
</style>
